// blur_gpu_gl.cpp
#include "blur_gpu_gl.h"
#include <GL/glew.h>
#include <SDL2/SDL_opengl.h>
#include <iostream>
#include <fstream>
#include <sstream>

// 检查是否支持 OpenGL
bool is_opengl_available() 
{
    return SDL_InitSubSystem(SDL_INIT_VIDEO) >= 0;
}

// 编译 GLSL 着色器
GLuint compile_shader(GLenum type, const std::string &source) 
{
    GLuint shader = glCreateShader(type);
    const char *src = source.c_str();
    glShaderSource(shader, 1, &src, nullptr);
    glCompileShader(shader);

    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE) {
        char log[512];
        glGetShaderInfoLog(shader, sizeof(log), nullptr, log);
        std::cerr << "Shader compile error: " << log << std::endl;
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

// 创建着色器程序
GLuint create_shader_program(const std::string &vertex_src, const std::string &fragment_src) {
    GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_src);
    GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_src);

    GLuint program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);

    GLint link_status;
    glGetProgramiv(program, GL_LINK_STATUS, &link_status);
    if (link_status != GL_TRUE) {
        char log[512];
        glGetProgramInfoLog(program, sizeof(log), NULL, log);
        std::cerr << "Shader link error: " << log << std::endl;
        glDeleteProgram(program);
        return 0;
    }

    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

// 读取文件内容
std::string read_file(const std::string &path) {
    std::ifstream file(path);
    std::stringstream buffer;
    buffer << file.rdbuf();
    return buffer.str();
}

// 使用 OpenGL 渲染模糊效果
void apply_blur_gpu(SDL_Surface *src, SDL_Surface *dst) {
    // 初始化 OpenGL
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
    SDL_Window *window = SDL_CreateWindow("GPU Blur", 0, 0, src->w, src->h, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
    SDL_GLContext context = SDL_GL_CreateContext(window);
    glewExperimental = GL_TRUE;
    glewInit();

    // 创建纹理
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src->w, src->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, src->pixels);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 创建帧缓冲区
    GLuint fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

    // 加载着色器
    std::string vertex_shader = read_file("shaders/blur_vertex.glsl");
    std::string fragment_shader = read_file("shaders/blur_fragment.glsl");

    GLuint program = create_shader_program(vertex_shader, fragment_shader);
    glUseProgram(program);

    // 设置 uniform 变量
    GLint width_loc = glGetUniformLocation(program, "width");
    glUniform1i(width_loc, src->w);

    GLint resolution_loc = glGetUniformLocation(program, "resolution");
    glUniform2f(resolution_loc, static_cast<float>(src->w), static_cast<float>(src->h));

    // 绘制全屏四边形
    GLfloat quad[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
        -1.0f,  1.0f,
         1.0f,  1.0f
    };

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, quad);

    // 创建目标纹理
    GLuint dst_texture;
    glGenTextures(1, &dst_texture);
    glBindTexture(GL_TEXTURE_2D, dst_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src->w, src->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 绑定帧缓冲区
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_texture, 0);

    // 执行绘制
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    // 下载结果到 dst
    glReadPixels(0, 0, src->w, src->h, GL_BGRA, GL_UNSIGNED_BYTE, dst->pixels);

    // 清理资源
    glDeleteTextures(1, &texture);
    glDeleteTextures(1, &dst_texture);
    glDeleteFramebuffers(1, &fbo);
    glDeleteProgram(program);

    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
}